#!/usr/bin/env python

import os
import os.path
import sys
import struct
import collections


K4 = 4096
M1 = 1024 * 1024


raw_chunks = {}


def f_name(volid, chunk_id):
    return 'raw.%d.%d.dump' % (volid, chunk_id)


def download_raw(volid, chunk_id):
    fname = f_name(volid, chunk_id)
    if os.path.isfile(fname):
        return

    cmd = 'lich.inspect --chunkdump raw.%d.%d' % (volid, chunk_id)
    os.system(cmd)


def read_page(volid, chunk_id, chunk_off):
    download_raw(volid, chunk_id)
    if chunk_id not in raw_chunks:
        with open(f_name(volid, chunk_id), "rb") as f:
            bytes = f.read(M1)
            n = len(bytes)
            assert n == M1
            raw_chunks[chunk_id] = bytes
            # f.seek(chunk_off)
            # page = f.read(K4)
            # return page
    raw = raw_chunks[chunk_id]
    return raw[chunk_off:chunk_off+K4]


def main(volid, bitmap_chunk_id):
    d = {}
    error_count = 0
    with open('%d.img' % volid, 'wb') as mf:
        download_raw(volid, bitmap_chunk_id)
        with open(f_name(volid, bitmap_chunk_id), "rb") as f:
            bytes = f.read(M1)
            n = len(bytes)
            assert n == M1
            prev_chunk_id, prev_chunk_off = 0, 0
            for i in range(0, n, 8):
                chunk_id, chunk_off = struct.unpack('II', bytes[i:i+8])
                if chunk_id != 0:
                    print chunk_id, chunk_off
                    if prev_chunk_id == 0:
                        prev_chunk_id = chunk_id
                        prev_chunk_off = 0

                    if chunk_id != prev_chunk_id:
                        prev_chunk_off = 0
                        if chunk_id - prev_chunk_id != 1:
                            print '  id_error', prev_chunk_id, chunk_id, chunk_id - prev_chunk_id

                    if chunk_off - prev_chunk_off != K4:
                        print '  off_error', chunk_id, prev_chunk_off, chunk_off, chunk_off - prev_chunk_off
                        error_count += 1

                    prev_chunk_id = chunk_id
                    prev_chunk_off = chunk_off

                    if chunk_id not in d:
                        d[chunk_id] = []

                    d[chunk_id].append(chunk_off)
                    page = read_page(volid, chunk_id, chunk_off)
                    mf.write(page)

    od = collections.OrderedDict(sorted(d.items()))
    print
    for k, v in od.iteritems():
        n = len(v)
        assert n <= 255
        print k, n
        l = [str(x) for x in v]
        for i in range(0, n, 5):
            print '  ', '  '.join(l[i:i+5])
    print 'total =', len(d)
    print 'error =', error_count


if __name__ == '__main__':
    for x in sys.argv:
        # print x
        pass

    g_vol_id = int(sys.argv[1])
    if len(sys.argv) > 2:
        bitmap_chunk_id = int(sys.argv[2])
    else:
        bitmap_chunk_id = 21

    #
    main(g_vol_id, bitmap_chunk_id)
